<!doctype html>
<html>
<head>
<title>Bulls and Cows</title>
<style>
body{background:lightgray;color:black;}
.btn{background:orange;color:black;}
.red{background:red;color:white;}
.blue{background:blue;color:white;}
.green{background:green;color:white;}
td{border:2px solid orange;}
h4{margin:5px;}
span{border:1px solid black;}
span.t1{background:black;}
span.t2{background:orange; color:black}
span.t3{background:white;}
</style>
</head>
<body>
<script>
function BullsAndCows(){

var count = 4;

this.v = function isValidNum(num){
var nu=parseInt(num);
if(isNaN(nu) || nu < 1023 || nu >9876){
return false;
}

var n = ""+num;
if(n.length != count){
return false;
}

for(var i=0; i < count; i++){
   for(var j=i-1; j >=0; j--){
      if(n[i] == n[j]){
         return false;
      }
   }
}

return true;
};//End this.v

this.bc = function(num, guess){
var bc = {};
bc.b = 0;
bc.c = 0;
bc.toString = function(){return "Bulls:" + this.b + "; Cows:" + this.c};

var g = guess.toString();
var n = num.toString();

for(var i=0; i<count; i++){
   for(var j=0; j<count; j++){
      if(g[i]==n[j]){
         if(i==j) bc.b++;
         else bc.c++;
      }
   }
}

return bc;
};//End this.bc

};//End BullsAndCows


function BullsAndCowsAI(num){
this.num = num;
var b = new BullsAndCows();
this.nums = [];

if(!num){
   for(var i=1023; i<=9876;i++){
      if(b.v(i)) this.nums.push(i);
   }
}

this.answer=function(guess){
var bc = b.bc(this.num, guess);
return bc;
};

this.guess=function(){
return this.nums[parseInt(Math.random()*this.nums.length)];
};

if(!num){
this.num=this.guess();
}

this.getInfo=function(guess, bc){

newNums = [];
var length = this.nums.length;
for(var i=0; i<length; i++){
   var tNum = this.nums[i];
   var tBc = b.bc(tNum, guess);
   if(tBc.b==bc.b && tBc.c==bc.c){
      newNums.push(tNum);
   }
}

this.nums = newNums;
};

};//End BullsAndCowsAI

function BullsAndCowsGame(){

this.i=0;
var states=
["name1",
"name2",
"num1",
"num2",
"p1",
"p2",
"w1",
"w2",
"=="];

this.b=new  BullsAndCows();

var ai1=false;
var ai2=false;

this.p1=null;
this.p2=null;

this.name1=null;
this.name2=null;

this.p1HasGuessed=false;

this.lastNum=null;
this.lastBc=null;
var self=this;

this.message=function(){
if(self.i==0){
   return "Input name for player1 or leave blank for computer!";
}
else if(self.i==1){
   return "Input name for player2 or leave blank for computer!";
}
else if(self.i==2){
   return self.name1 + ": Input secret number!";
}
else if(self.i==3){
   return self.name2 + ": Input secret number!";
}
else if(self.i==4){
   return self.name1 + ": Make guess!";
}
else if(self.i==5){
   return self.name2 + ": Make guess!";
}
else if(self.i==6){
   return self.name1 + " wins!";
}
else if(self.i==7){
   return self.name2 + " wins!";
}
else if(self.i==8){
   return "Game over! No one wins!";
}
else{
   return "Something went wrong! Kill the developer!";
}
};//end this.message

this.play=function(inp){

if(self.i>5){
   return false;
}//end game is over

if(self.i==0){
   self.name1=inp;
   if(inp==""){
      self.name1="Computer1";
      ai1=true;
      self.p1=new BullsAndCowsAI();
   }
   self.i++;
   return true;
}//end i==0

if(self.i==1){
   self.name2=inp;
   if(inp==""){
      self.name2="Computer2";
      ai2=true;
      self.p2=new BullsAndCowsAI();
   }
   self.i++;
   if(ai1){
      self.i++;
      if(ai2){
         self.i++;
      }
   }
   return true;
}//end i==1

if(ai1 &&  self.i==4){
   inp=self.p1.guess();
}
if(ai2 && self.i==5){
   inp=self.p2.guess();
}

var isValid=self.b.v(inp);
if(!isValid){
   return false;
}

var num=parseInt(inp);
self.lastNum=num;

if(self.i==2){
   self.p1=new BullsAndCowsAI(num);
   self.i++;
   if(ai2){
      self.i++;
   }
   return true;
}//end i==2

if(self.i==3){
   self.p2=new BullsAndCowsAI(num);
   self.i++;
   return true;
}//end i==3

if(self.i==4){
   if(num==self.p2.num){
      self.p1HasGuessed=true;
   }
   self.lastBc=self.p2.answer(num);
   if(ai1) self.p1.getInfo(num,self.lastBc);
   self.i++;
}//end p1
else if(self.i==5){
   self.lastBc=self.p1.answer(num);
   if(ai2) self.p2.getInfo(num,self.lastBc);
   self.i--;

   if(num==self.p1.num){
      if(self.p1HasGuessed) self.i=8;
      else self.i=7;
   }
   else  if(self.p1HasGuessed){ 
      self.i=6;
   }

return true;
}//end p2

return true;
};//end this.play

};//End BullsAndCowsGame

function BullsAndCowsUI(){
this.w = function(text){document.write(""+text);};
this.wl = function(text){document.write(""+text+"<br />");};

this.a = function(text){alert(""+text);};

this.g= new BullsAndCowsGame();

var self=this;

this.id=function(id){
   return document.getElementById(""+id);
};

this.style=function(el){
var cl=el.className;
if(cl=="t1") el.className="t2";
else if(cl=="t2") el.className="t3";
else if(cl=="t3") el.className="t1";
};

this.showMsg=function(state){
if(state<8){
   self.cl(self.id("gameMsg"),((state%2==0)?"red":"blue"));
}
else{
   self.cl(self.id("gameMsg"),"green");
}
   var msg=self.g.message();
    var el=self.id("gameMsg");
    el.innerHTML=""+msg;
};

this.cl=function(el,classN){
el.className=classN;
};

this.busy=function(id){
self.cl(self.id(id),"busy");
};

this.free=function(id){
self.cl(self.id(id),"free");
};

this.p=function(el,text){
el.innerHTML+=text+"<br />";
};

this.p1=function(text){
self.p(self.id("p1"),text);
};

this.p2=function(text){
self.p(self.id("p2"),text);
};

this.input=function(){

   var el=self.id("inp");
   var inp=el.value;
   var state=self.g.i;

   var valid=self.g.play(inp);
   self.showMsg(self.g.i);
   if(valid){
      el.value="";
      if(state==0) self.id("h1").innerHTML=self.g.name1;
      else if(state==1) self.id("h2").innerHTML=self.g.name2;
      else if(state==4) self.p1(self.g.lastNum+": "+self.g.lastBc);
      else if(state==5) self.p2(self.g.lastNum+": "+self.g.lastBc);
      alert("OK!");
   }
   else{
     if(state<6) alert("Invalid input: "+inp+"! Try again!");
      else alert("Game over! ");
   }

};//end this.input

};//End BullsAndCowsUI

</script>

<script>
var d = new BullsAndCowsUI();
</script>

<div id="BaC">
<h3 id="gameMsg" class="green">FATAL ERROR!</h3>
<input type="text" id="inp" class="free"/>
<button  onclick="d.input()" id="btn" class="btn">PLAY</button>
</div>
<table>
<tr>
<td class="red">
   <h4 id="h1">Player1</h4>
   <div onclick="d.style(window.event.srcElement)">
        <span class="t1">0</span>
        <span class="t1">1</span>
        <span class="t1">2</span>
        <span class="t1">3</span>
        <span class="t1">4</span>
        <span class="t1">5</span>
        <span class="t1">6</span>
        <span class="t1">7</span>
        <span class="t1">8</span>
        <span class="t1">9</span>
   </div>
   <textarea rows="1" cols="10">xxxx</textarea>
   <div id="p1"></div>
</td>
<td class="blue">
   <h4 id="h2">Player2</h4>
   <div onclick="d.style(window.event.srcElement)">
        <span class="t1">0</span>
        <span class="t1">1</span>
        <span class="t1">2</span>
        <span class="t1">3</span>
        <span class="t1">4</span>
        <span class="t1">5</span>
        <span class="t1">6</span>
        <span class="t1">7</span>
        <span class="t1">8</span>
        <span class="t1">9</span>
   </div>
   <textarea rows="1" cols="10">xxxx</textarea>
   <div id="p2"></div>
</td>
</tr>
</table>

<script>
d.showMsg(0);
</script>

</body>
</html>